package interpreter.bytecodes;

import interpreter.VirtualMachine;
import java.util.NoSuchElementException;
import java.util.Vector;

/**
 *
 * @author Kristofer Selbekk
 */
public class BopByteCode extends ByteCode {

    private String op; // The operator given


    /**
     * Initializes the byte code with 1 argument
     */
    public void init( Vector<String> args ) {
        try {
            op = args.get(0);
            // Validate operator
        } catch( NumberFormatException nfe ) {
            // If bad format
            System.out.println("Bad format!");
            System.exit(-1);
        } catch( NoSuchElementException nse ) {
            // If empty argument
            System.out.println("Empty vector!");
            System.exit(-1);
        } catch( NullPointerException npe ) {
            // If argument missing
            System.out.println("Argument given = null.");
            System.exit(-1);
        }
    }

    /**
     * Action: Get top two elements off stack, do operation on them, put back the result
     *
     * @param rt the Virtual Machine reference
     */
    public void exec( VirtualMachine rt ) {
        // Checks for enough elements
        if( rt.getStackSize() < 2) {
            System.out.println("ERROR: Stack does not have enough elements!");
            return;
        }

        // Gets the elements
        int elem2 = rt.popStack();
        int elem1 = rt.popStack();
        int answer = 0; //

        // Decides what kind of operation is done
        // Yes it's ugly, I know. BUT it's easy to see the logic and it works perfectly
        if( op.equals("+") ) {                  // addition
            answer = elem1 + elem2;
        } else if( op.equals("-") ) {           // negation
            answer = elem1 - elem2;
        } else if( op.equals("/") ) {           // integer division
            if( elem2 == 0) elem2 = 1; // Quick fix for division by zero, do nothing
            answer = elem1 / elem2;
        } else if( op.equals("*") ) {           // multiplication
            answer = elem1 * elem2;
        } else if( op.equals("==") ) {          // equality
            if( elem1 == elem2 ) answer = 1; // 1 is true, 0 is false
            else answer = 0;
        } else if( op.equals("!=") ) {          // inequality
            if( elem1 != elem2 ) answer = 1;
            else answer = 0;
        } else if( op.equals("<=") ) {          // equality or less than
            if( elem1 <= elem2 ) answer = 1;
            else answer = 0;
        } else if( op.equals(">=") ) {          // equality or more than
            if( elem1 >= elem2 ) answer = 1;
            else answer = 0;
        } else if( op.equals(">") ) {           // more than
            if( elem1 > elem2 ) answer = 1;
            else answer = 0;
        } else if( op.equals("<") ) {           // less than
            if( elem1 < elem2 ) answer = 1;
            else answer = 0;
        } else if( op.equals("|") ) {           // logical or
            if( elem1 != 0 || elem2 != 0) answer = 1;
            else answer = 0;
        } else if( op.equals("&") ) {           // logical and
            if( elem1 != 0 && elem2 != 0 ) answer = 1;
            else answer = 0;
        } 
        // Saves answer on top of stack
        rt.pushOnStack( answer );
    }

    public Object getArgs() {
        return op;
    }
}